import fs from 'fs'
import path from 'path'
import { prisma } from './db'
import { HttpsProxyAgent } from 'https-proxy-agent'
import fetch from 'node-fetch'

// 确保下载目录存在
const DOWNLOAD_BASE_DIR = path.join(process.cwd(), 'downloads')
const VIDEO_DIR = path.join(DOWNLOAD_BASE_DIR, 'videos')
const AUDIO_DIR = path.join(DOWNLOAD_BASE_DIR, 'audio')
const COVER_DIR = path.join(DOWNLOAD_BASE_DIR, 'covers')

// 创建目录
function ensureDirectories() {
  [DOWNLOAD_BASE_DIR, VIDEO_DIR, AUDIO_DIR, COVER_DIR].forEach(dir => {
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true })
    }
  })
}

// 创建带代理的fetch配置
function createProxyFetchOptions(): any {
  const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY

  if (!proxyUrl) {
    return {}
  }

  console.log('配置下载代理:', proxyUrl)

  // 创建代理agent
  const agent = new HttpsProxyAgent(proxyUrl)

  return {
    agent: agent
  }
}

// 带重试机制的下载函数
async function downloadFileWithRetry(url: string, filePath: string, maxRetries: number = 3): Promise<{ success: boolean, size?: number, error?: string }> {
  let lastError: Error | null = null
  const proxyOptions = createProxyFetchOptions()

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      console.log(`下载文件 (${attempt}/${maxRetries}):`, url)

      const response = await fetch(url, {
        headers: {
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
          'Accept': '*/*',
          'Accept-Language': 'en-US,en;q=0.5',
          'Accept-Encoding': 'gzip, deflate, br',
          'Connection': 'keep-alive',
          'Referer': 'https://www.tiktok.com/',
          'Sec-Fetch-Dest': 'video',
          'Sec-Fetch-Mode': 'no-cors',
          'Sec-Fetch-Site': 'cross-site'
        },
        ...proxyOptions,
        timeout: 60000 // 60秒超时
      })

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
      }

      const buffer = await response.buffer()

      // 确保目录存在
      const dir = path.dirname(filePath)
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true })
      }

      fs.writeFileSync(filePath, buffer)

      console.log(`文件下载成功 (尝试 ${attempt}):`, filePath, `大小: ${buffer.length} bytes`)
      return { success: true, size: buffer.length }

    } catch (error) {
      lastError = error instanceof Error ? error : new Error('Unknown error')
      console.warn(`下载失败 (尝试 ${attempt}/${maxRetries}):`, lastError.message)

      if (attempt < maxRetries) {
        // 指数退避：2秒、4秒、8秒
        const delay = Math.pow(2, attempt) * 1000
        console.log(`等待 ${delay}ms 后重试...`)
        await new Promise(resolve => setTimeout(resolve, delay))
      }
    }
  }

  return { success: false, error: lastError?.message || 'Download failed' }
}

// 下载文件的通用函数（保持向后兼容）
async function downloadFile(url: string, filePath: string): Promise<{ success: boolean, size?: number, error?: string }> {
  return downloadFileWithRetry(url, filePath, 3)
}

// 获取文件扩展名
function getFileExtension(url: string, defaultExt: string): string {
  try {
    const urlObj = new URL(url)
    const pathname = urlObj.pathname
    const ext = path.extname(pathname)
    return ext || defaultExt
  } catch {
    return defaultExt
  }
}

// 下载视频文件
export async function downloadVideoFiles(videoId: number): Promise<{ success: boolean, error?: string }> {
  try {
    ensureDirectories()

    // 获取视频信息
    const video = await prisma.tikTokVideo.findUnique({
      where: { id: videoId }
    })

    if (!video) {
      return { success: false, error: 'Video not found' }
    }

    // 更新下载状态为进行中
    await prisma.tikTokVideo.update({
      where: { id: videoId },
      data: {
        downloadStatus: 'downloading',
        downloadProgress: 0
      }
    })

    let totalFiles = 0
    let completedFiles = 0
    let totalSize = 0

    // 计算需要下载的文件数量
    if (video.videoUrl) totalFiles++
    if (video.audioUrl) totalFiles++
    if (video.coverUrl) totalFiles++

    if (totalFiles === 0) {
      await prisma.tikTokVideo.update({
        where: { id: videoId },
        data: {
          downloadStatus: 'failed',
          downloadProgress: 0
        }
      })
      return { success: false, error: 'No downloadable URLs found' }
    }

    const results: { type: string, success: boolean, path?: string, size?: number, error?: string }[] = []

    // 下载视频文件
    if (video.videoUrl) {
      const videoExt = getFileExtension(video.videoUrl, '.mp4')
      const videoFileName = `${video.videoId}_video${videoExt}`
      const videoPath = path.join(VIDEO_DIR, videoFileName)
      
      const result = await downloadFile(video.videoUrl, videoPath)
      results.push({
        type: 'video',
        success: result.success,
        path: result.success ? videoPath : undefined,
        size: result.size,
        error: result.error
      })
      
      if (result.success) {
        completedFiles++
        totalSize += result.size || 0
        await prisma.tikTokVideo.update({
          where: { id: videoId },
          data: {
            localVideoPath: videoPath,
            downloadProgress: Math.round((completedFiles / totalFiles) * 100)
          }
        })
      }
    }

    // 下载音频文件
    if (video.audioUrl) {
      const audioExt = getFileExtension(video.audioUrl, '.mp3')
      const audioFileName = `${video.videoId}_audio${audioExt}`
      const audioPath = path.join(AUDIO_DIR, audioFileName)
      
      const result = await downloadFile(video.audioUrl, audioPath)
      results.push({
        type: 'audio',
        success: result.success,
        path: result.success ? audioPath : undefined,
        size: result.size,
        error: result.error
      })
      
      if (result.success) {
        completedFiles++
        totalSize += result.size || 0
        await prisma.tikTokVideo.update({
          where: { id: videoId },
          data: {
            localAudioPath: audioPath,
            downloadProgress: Math.round((completedFiles / totalFiles) * 100)
          }
        })
      }
    }

    // 下载封面图片
    if (video.coverUrl) {
      const coverExt = getFileExtension(video.coverUrl, '.jpg')
      const coverFileName = `${video.videoId}_cover${coverExt}`
      const coverPath = path.join(COVER_DIR, coverFileName)
      
      const result = await downloadFile(video.coverUrl, coverPath)
      results.push({
        type: 'cover',
        success: result.success,
        path: result.success ? coverPath : undefined,
        size: result.size,
        error: result.error
      })
      
      if (result.success) {
        completedFiles++
        totalSize += result.size || 0
        await prisma.tikTokVideo.update({
          where: { id: videoId },
          data: {
            localCoverPath: coverPath,
            downloadProgress: Math.round((completedFiles / totalFiles) * 100)
          }
        })
      }
    }

    // 更新最终状态
    const allSuccessful = results.every(r => r.success)
    const anySuccessful = results.some(r => r.success)

    await prisma.tikTokVideo.update({
      where: { id: videoId },
      data: {
        downloadStatus: allSuccessful ? 'completed' : anySuccessful ? 'partial' : 'failed',
        downloadProgress: 100,
        fileSize: totalSize
      }
    })

    if (allSuccessful) {
      return { success: true }
    } else {
      const errors = results.filter(r => !r.success).map(r => `${r.type}: ${r.error}`).join('; ')
      return { success: anySuccessful, error: errors }
    }

  } catch (error) {
    // 更新状态为失败
    await prisma.tikTokVideo.update({
      where: { id: videoId },
      data: {
        downloadStatus: 'failed',
        downloadProgress: 0
      }
    })
    
    return { 
      success: false, 
      error: error instanceof Error ? error.message : 'Unknown error' 
    }
  }
}

// 批量下载多个视频
export async function downloadMultipleVideos(videoIds: number[]): Promise<{ success: number, failed: number, errors: string[] }> {
  let success = 0
  let failed = 0
  const errors: string[] = []

  for (const videoId of videoIds) {
    const result = await downloadVideoFiles(videoId)
    if (result.success) {
      success++
    } else {
      failed++
      if (result.error) {
        errors.push(`Video ${videoId}: ${result.error}`)
      }
    }
  }

  return { success, failed, errors }
}

// 获取文件下载状态
export async function getDownloadStatus(videoId: number) {
  const video = await prisma.tikTokVideo.findUnique({
    where: { id: videoId },
    select: {
      downloadStatus: true,
      downloadProgress: true,
      localVideoPath: true,
      localAudioPath: true,
      localCoverPath: true,
      fileSize: true
    }
  })

  return video
}

// 清理本地文件
export async function cleanupLocalFiles(videoId: number): Promise<{ success: boolean, error?: string }> {
  try {
    const video = await prisma.tikTokVideo.findUnique({
      where: { id: videoId },
      select: {
        localVideoPath: true,
        localAudioPath: true,
        localCoverPath: true
      }
    })

    if (!video) {
      return { success: false, error: 'Video not found' }
    }

    // 删除本地文件
    const filesToDelete = [video.localVideoPath, video.localAudioPath, video.localCoverPath]
      .filter(Boolean) as string[]

    for (const filePath of filesToDelete) {
      if (fs.existsSync(filePath)) {
        fs.unlinkSync(filePath)
      }
    }

    // 更新数据库
    await prisma.tikTokVideo.update({
      where: { id: videoId },
      data: {
        localVideoPath: null,
        localAudioPath: null,
        localCoverPath: null,
        downloadStatus: 'pending',
        downloadProgress: 0,
        fileSize: null
      }
    })

    return { success: true }
  } catch (error) {
    return { 
      success: false, 
      error: error instanceof Error ? error.message : 'Unknown error' 
    }
  }
}
